/**
 * Copyright (c) 2008,中企动力华南研发中心 All rights reserved.
 */
package com.ce.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;


/**
 * 逻辑、功能相关描述:上传工具类
 *
 * @author 姜川 编写日期：2008-1-21
 */
public class MutilpartUploadUtil {

	private static String PMS_UPLOAD_PATH = "upload";

   //	private static String TMP = "tmp";


	/**
	 * Function:将文件写入HttpServletResponse 输出流 参数filePath 必须为从数据库读出的路径
	 * @param request
	 * @param response
	 * @param filePath
	 * @throws IOException
	 * @return
	 * Create author:姜川
	 * Create on:2008-1-21
	 * Edit author:
	 * Edit on:
	 * Why:
	 */
	public static void writeResponseOutputStream(HttpServletRequest request,
			HttpServletResponse response,
			String filePath) throws IOException{

		writeResponseOutputStream(request, response, filePath,false);
	}


	/**
	 * Function:方法描述：将文件写入HttpServletResponse 输出流 参数filePath 必须为绝对路径
	 * @param request
	 * @param response
	 * @param filePath
	 * @throws IOException
	 * @return
	 * Create author:姜川
	 * Create on:2008-1-21
	 * Edit author:
	 * Edit on:
	 * Why:
	 */
	public static void writeResponseOutputStreamByAbsPath(HttpServletRequest request,
			HttpServletResponse response,
			String filePath) throws IOException{

		writeResponseOutputStream(request,response,filePath,true);
	}


	/**
	 * Function:方法描述：将文件写入HttpServletResponse 输出流
	 *   本方法只读取传入的文件,将文件写入response,并不设置response.contentPath及response.header,
	 *   在使用本方法进行方法下载时,需要自行设置,在设置header的filename时,
	 *   可使用java.net.URLEncoder.encode(fileName,"UTF-8")处理文件名
	 *
	 * @param request
	 * @param response
	 * @param filePath
	 * @throws IOException
	 * @return
	 * Create author:姜川
	 * Create on:2008-1-21
	 * Edit author:
	 * Edit on:
	 * Why:
	 */
	private static void writeResponseOutputStream(HttpServletRequest request,
												HttpServletResponse response,
												String filePath,boolean isAbs) throws IOException {
		BufferedInputStream bis = null;

		BufferedOutputStream bos = null;

		try {

			String absPath = null;

			if (isAbs) {
				absPath = filePath;
			} else {
				absPath = getAbsFilePath(request,filePath);
			}

			File file = new File(absPath);

			if (!file.exists()) return;

		    bis = new BufferedInputStream(new FileInputStream(file));

		    bos = new BufferedOutputStream(response.getOutputStream());

		    byte[] buff = new byte[2048];

		    int bytesRead;

		    while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
		        bos.write(buff,0,bytesRead);
		    }

		} catch (final IOException e) {
			e.printStackTrace();
		    throw e;
		} finally {

		    if (bis != null)
		        bis.close();
		    if (bos != null)
		        bos.close();
		}

	}


	/**
	 * Function:方法描述：删除文件
	 * @param request
	 * @param removeFilePath 删除文件的数据库路径
	 * @param fileName 文件名
	 * @return
	 * Create author:姜川
	 * Create on:2008-1-21
	 * Edit author:
	 * Edit on:
	 * Why:
	 */
	public static boolean removeFile(HttpServletRequest request,
									 String removeFilePath,
									 String fileName) {

		if (removeFilePath != null && !removeFilePath.trim().equals("")) {
			//当前路径
			String realPath = request.getSession().getServletContext().getRealPath("");

			realPath += File.separator + removeFilePath + fileName;

			File file = new File(realPath);

			if (file.exists()) {
				return file.delete();
			}
		}
		return false;
	}



	/**
	 * Function:构造返回的相对路径,该路径可直接写入数据库,如返回:/pms.upload(注:这里去掉.war)/aaa/aaa.jpg
	 * @param path 文件完整路径,可将uploadImg()方法返回的完整路径传入
	 * @return
	 * Create author:姜川
	 * Create on:2008-1-21
	 * Edit author:
	 * Edit on:
	 * Why:
	 */
	public static String getToDateBaseFilePath(String path) {

		if(path == null || path.equals("")) return "";

		String fileName = path;

		fileName = fileName.substring(fileName.indexOf(PMS_UPLOAD_PATH));
		return fileName;
	}



	/**
	 * Function:得到pms.upload.war的绝对路径
	 * @param request
	 * @return
	 * Create author:姜川
	 * Create on:2008-1-21
	 * Edit author:
	 * Edit on:
	 * Why:
	 */
	public static String getAbsFilePath(HttpServletRequest request) {

		String realPath = request.getSession().getServletContext().getRealPath("");

		realPath += File.separator + PMS_UPLOAD_PATH;

		return realPath;
	}


	/**
	 * Function:得到绝对路径
	 * @param request
	 * @param dbFilePath
	 * @return
	 * Create author:姜川
	 * Create on:2008-1-21
	 * Edit author:
	 * Edit on:
	 * Why:
	 */
	public static String getAbsFilePath(HttpServletRequest request,String dbFilePath) {

		String realPath = request.getSession().getServletContext().getRealPath("upload");

		realPath += File.separator + dbFilePath;

		System.out.println("realPath--->"+realPath);

		return realPath;
	}


	/**
	 * Function:上传文件到服务器
	 * @param request
	 * @param toDir 保存上传文件目录upload的子目录
	 * @param newFileName 把上传的文件以此名字保存
	 * @return  返回符合保存文件后的Map<String,String > key是页面字段的file的 Name ,Value 是文件的相对路径如:upload\\cs\newFileName.gif
	 * Create author:姜川
	 * Create on:2008-1-21
	 * Edit author:
	 * Edit on:
	 * Why:
	 */
	public static Map<String, Map<String,String>> uploadToServer(HttpServletRequest request,
						String toDir ,
						String newFileName)
						throws IOException,ServletException, FileUploadException{

		String foldNamePath=  request.getSession().getServletContext().getRealPath("upload");

		//Create a factory for disk-based file items
		FileItemFactory factory = new DiskFileItemFactory();

		//设置最多只允许在内存中存储的数据,单位:字节5M
		((DiskFileItemFactory) factory).setSizeThreshold(5242880);

		//设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录
	    String	tempFile = foldNamePath + File.separator + "Temp";

		 File filePath = new File(tempFile);

			((DiskFileItemFactory) factory).setRepository(filePath);

		if ((toDir!=null)&&(!toDir.equals(""))) {
			foldNamePath = foldNamePath+ File.separator +toDir+ File.separator;
		}

		//Create a new file upload handler
		ServletFileUpload upload = new ServletFileUpload(factory);

		//设置允许用户上传文件大小,单位:字节10M
		upload.setSizeMax(10000000);

	    List fileItems=null;

	try {

		fileItems = upload.parseRequest(request);

	} catch (FileUploadException e1) {
		// TODO Auto-generated catch block
		e1.printStackTrace();
	}

		Map<String, String> paraFile = new HashMap<String, String>();// 保存id
																	// 的name ,
		Map<String, String> paraType = new HashMap<String, String>();// 保存name
																		// 和text
		Map<String, Map<String, String>> returnMap = new HashMap<String, Map<String, String>>();// 保存name
																								// 和text
		Iterator iter = fileItems.iterator();

		while (iter.hasNext()) {

			FileItem fi = (FileItem) iter.next();

			if (!fi.isFormField()) {

				String fileName = fi.getName();
				String enCodingFilename = fileName;
				File tempFileRef = new File(enCodingFilename);
				// Create a new directory
				File testDir = new File(foldNamePath);
				if (!testDir.exists()) {
					testDir.mkdirs();
				}
				// 原始的文件路径
				if ((fi.getName() != null) && (fi.getName() != "")) {
					//File fNew = new File(foldNamePath, tempFileRef.getName());
					String fname = tempFileRef.getName();

					if(newFileName!=null && !"".equals(newFileName)){
						fname = newFileName + fname.substring(fname.lastIndexOf("."));
					}
					//File fNew = new File(foldNamePath, fname);
					File fNew = createFile(foldNamePath, fname);
					String linuxFileName = getToDateBaseFilePath(fNew.getAbsolutePath());

					paraFile.put(fi.getFieldName(),	linuxFileName);
					try {
						fi.write(fNew);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			} else if (fi.isFormField()) { // 表单的其他信息
				String name = fi.getFieldName();
				String value = new String(fi.getString().getBytes("ISO8859_1"),"UTF-8");
				paraType.put(name, value);

			}
		}

		returnMap.put("fileType", paraFile);
		returnMap.put("paraType", paraType);
		return returnMap;
	}

	private static File createFile (String foldPath, String fileName) {

		File fNew = new File(foldPath, fileName);

		int count = 0;

		while (fNew.exists()) {
			count++;
			if (fileName.indexOf("(") == -1) {
				fileName = fileName.substring(0, fileName.lastIndexOf("."))+"(" + count + ")" + fileName.substring(fileName.lastIndexOf("."));
			} else {
				fileName = fileName.substring(0, fileName.indexOf("("))+"(" + count + ")" + fileName.substring(fileName.lastIndexOf("."));
			}
			fNew = new File(foldPath, fileName);
		}
		return fNew;
	}

//	public static void main(String[] args) throws FileNotFoundException {
//		File f = createFile("d:\\","a(1).txt");
//		FileOutputStream o = new FileOutputStream(f);
//	}
}


